//
//  TYZBaseRequest.m
//  DrivieSchoolStudents
//
//  Created by TangBin on 2019/5/29.
//  Copyright © 2019 班文政. All rights reserved.
//

#import "TYZBaseRequest.h"
#import "TYZNetworkAgent.h"
#import "TYZNetworkPrivate.h"
#import <AFNetworking/AFNetworking.h>

NSString *const TYZRequestValidationErrorDomain = @"com.tb.request.validation";

@interface TYZBaseRequest ()

@property (nonatomic, strong, readwrite) NSURLSessionTask *requestTask;
@property (nonatomic, strong, readwrite) NSData *responseData;
@property (nonatomic, strong, readwrite) id responseJSONObject;
@property (nonatomic, strong, readwrite) id responseObject;
@property (nonatomic, strong, readwrite) NSString *responseString;
@property (nonatomic, strong, readwrite) NSError *error;

@end

@implementation TYZBaseRequest

#pragma mark - Request and Response Information

- (NSHTTPURLResponse *)response
{
    return (NSHTTPURLResponse *)self.requestTask.response;
}

- (NSInteger)responseStatusCode
{
    return self.response.statusCode;
}

- (NSDictionary *)responseHeaders
{
    return self.response.allHeaderFields;
}

- (NSURLRequest *)currentRequest
{
    return self.requestTask.currentRequest;
}

- (NSURLRequest *)originalRequest
{
    return self.requestTask.originalRequest;
}

- (BOOL)isCancelled
{
    if (!self.requestTask)
    {
        return NO;
    }
    return self.requestTask.state == NSURLSessionTaskStateCanceling;
}

- (BOOL)isExecuting
{
    if (!self.requestTask)
    {
        return NO;
    }
    return self.requestTask.state == NSURLSessionTaskStateRunning;
}

#pragma mark - Request Configuration

- (void)setCompletionBlockWithSuccess:(TYZRequestCompletionBlock)success failure:(TYZRequestCompletionBlock)failure
{
    self.successCompletionBlock = success;
    self.failureCompletionBlock = failure;
}

- (void)clearCompletionBlock
{
    self.successCompletionBlock =  nil;
    self.failureCompletionBlock = nil;
}

#pragma mark - Request Action

- (void)start
{
    [[TYZNetworkAgent sharedInstance] addRequest:self];
}

- (void)stop
{
    [[TYZNetworkAgent sharedInstance] cancelRequest:self];
}

- (void)startWithCompletionBlockWithSuccess:(TYZRequestCompletionBlock)success failure:(TYZRequestCompletionBlock)failure
{
    [self setCompletionBlockWithSuccess:success failure:failure];
    [self start];
}


#pragma mark - Subclass Override
///=============================================================================
/// @name Subclass Override
///=============================================================================

///  Called on background thread after request succeded but before switching to main thread. Note if 缓存是否要处理
///  cache is loaded, this method WILL be called on the main thread, just like `requestCompleteFilter`.
- (void)requestCompletePreprocessor
{
    
}

///  Called on the main thread after request succeeded. 是否要过滤
- (void)requestCompleteFilter
{
    
}

///  Called on background thread after request failed but before switching to main thread. See also
///  `requestCompletePreprocessor`.
- (void)requestFailedPreprocessor
{
    
}

///  Called on the main thread when request failed.
- (void)requestFailedFilter
{
    
}

///  The baseURL of request. This should only contain the host part of URL, e.g., http://www.example.com.
///  See also `requestUrl`
- (NSString *)baseUrl
{
    return @"";
}

///  The URL path of request. This should only contain the path part of URL, e.g., /v1/user. See alse `baseUrl`.
///
///  @discussion This will be concated with `baseUrl` using [NSURL URLWithString:relativeToURL].
///              Because of this, it is recommended that the usage should stick to rules stated above.
///              Otherwise the result URL may not be correctly formed. See also `URLString:relativeToURL`
///              for more information.
///
///              Additionaly, if `requestUrl` itself is a valid URL, it will be used as the result URL and
///              `baseUrl` will be ignored.
- (NSString *)requestUrl
{
    return @"";
}

///  Optional CDN URL for request.
- (NSString *)cdnUrl
{
    return @"";
}

///  Requset timeout interval. Default is 60s.
///
///  @discussion When using `resumableDownloadPath`(NSURLSessionDownloadTask), the session seems to completely ignore
///              `timeoutInterval` property of `NSURLRequest`. One effective way to set timeout would be using
///              `timeoutIntervalForResource` of `NSURLSessionConfiguration`.
- (NSTimeInterval)requestTimeoutInterval
{
    return 60;
}

///  Additional request argument.
- (id)requestArgument
{
    return nil;
}

///  Override this method to filter requests with certain arguments when caching.
- (id)cacheFileNameFilterForRequestArgument:(id)argument
{
    return argument;
}

///  HTTP request method.
- (TYZRequestMethod)requestMethod
{
    return TYZRequestMethodGET;
}

///  Request serializer type.
- (TYZRequestSerializerType)requestSerializerType
{
    return TYZRequestSerializerTypeHTTP;
}

///  Response serializer type. See also `responseObject`.
- (TYZResponseSerializerType)responseSerializerType
{
    return TYZResponseSerializerTypeJSON;
}

///  Username and password used for HTTP authorization. Should be formed as @[@"Username", @"Password"].
- (NSArray<NSString *> *)requestAuthorizationHeaderFieldArray
{
    return nil;
}

///  Additional HTTP request header field.
- (NSDictionary<NSString *, NSString *> *)requestHeaderFieldValueDictionary
{
    return nil;
}

///  Use this to build custom request. If this method return non-nil value, `requestUrl`, `requestTimeoutInterval`,
///  `requestArgument`, `allowsCellularAccess`, `requestMethod` and `requestSerializerType` will all be ignored.
- (NSURLRequest *)buildCustomUrlRequest
{
    return nil;
}

///  Whether the request is allowed to use the cellular radio (if present). Default is YES.(请求是否允许使用蜂窝无线电(如果存在)。默认是肯定的。)
- (BOOL)allowsCellularAccess
{
    return YES;
}

///  The validator will be used to test if `responseJSONObject` is correctly formed.
- (id)jsonValidator
{
    return nil;
}

///  This validator will be used to test if `responseStatusCode` is valid.
- (BOOL)statusCodeValidator
{
    NSInteger statusCode = [self responseStatusCode];
    return (statusCode >= 200 && statusCode <= 299);
}

/**
 解析数据
 */
- (void)handleParseData
{
    
}

#pragma mark - NSObject

- (NSString *)description
{
    return [NSString stringWithFormat:@"<%@: %p>{ URL: %@ } { method: %@ } { arguments: %@ }", NSStringFromClass([self class]), self, self.currentRequest.URL, self.currentRequest.HTTPMethod, self.requestArgument];
}

@end


























